<?php

declare(strict_types=1);

namespace App\Library\Task\library\queue\drivers\mns;

use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Library\Log\Log;
use App\Library\Task\library\queue\drivers\DriverClientImp;
use Hyperf\Utils\ApplicationContext;

class QueueClientMns implements DriverClientImp
{
    private static $retryCount = 1;
    private $maxRetryCount = 5;


    /**
     * @param $key
     * @param $value
     * @param string $queueDriver
     * @return bool|mixed
     * 入列
     */
    public function push($key, $value, $queueDriver = 'default') {

        $queueDriver = str_replace('_', '-', $queueDriver);

        $data = serialize(array($key => $value));

        $queuedb = ApplicationContext::getContainer()->get(QueueDBMns::class);

        $result = $queuedb->push($data, $queueDriver);

        //失败重试
        if ($result['state'] === false) {
            $mnsError = $result['msg'];
            //判断错误消息需不需要进行重试
            $errorMsgRetry = false;
            if($mnsError->getMnsErrorCode() == 'ServerError'){
                $errorMsgRetry = true;
            }elseif (strpos($mnsError->getMessage(),'cURL error 28: Operation timed out') !== false){
                $errorMsgRetry = true;
            }
            if ($errorMsgRetry && self::$retryCount <= $this->maxRetryCount) {
                //mns 500错误重试
                Log::warning(new BusinessException(ErrorCode::OTHER_ERR, 'mns队列 push异常：' . sprintf('%s', $mnsError) . '; 第' . self::$retryCount . '次重试' . '; trace:' .  json_encode($mnsError->getTrace())));

                self::$retryCount += 1;
//                return self::push($key, $value, $queueDriver);
                return $this->push($key, $value, $queueDriver);
            }else{
                //不需要重试的或者重试完成还是报错的错误直接记录并报警
                Log::fatal(new BusinessException(ErrorCode::OTHER_ERR, 'mns队列 push异常：' . sprintf('%s', $mnsError) . '; trace:' . json_encode($mnsError->getTrace())));
            }
        }
        //重试次数重置为1
        self::$retryCount = 1;
        return $result['state'];
    }

}